import { Request, Response } from "express";
import { acceptLogoutRequest, getLogoutRequest } from "../services/hydra";
import {
    authenticationPrivateApi,
    getServiceNameFromApi,
    getErrorCodeFromService,
    eacpPublicApi,
} from "../core/config";
import { ErrorCode } from "../core/errorcode";

const signout = async (req: Request, res: Response) => {
    let { logout_challenge } = req.query;
    logout_challenge = req.query.logout_challenge || req.cookies.logout_challenge;
    let is_previous_login_3rd_party = req.cookies.is_previous_login_3rd_party;
    if (logout_challenge) {
        (res as Response).cookie("logout_challenge", logout_challenge);
        try {
            if (req.query.logout_challenge) {
                const lastTimestamp = Date.now();
                const { sid = "" } = await getLogoutRequest(logout_challenge as string);
                console.log(`[${Date()}] [INFO]  {/api/authentication/v1/session/${sid} DELETE} START`);
                await authenticationPrivateApi.delete(`/api/authentication/v1/session/${sid}`);
                console.log(
                    `[${Date()}] [INFO]  {/api/authentication/v1/session/${sid} DELETE} SUCCESS +${
                        Date.now() - lastTimestamp
                    }ms`
                );
            } else {
                (res as Response).clearCookie("is_previous_login_3rd_party");
                is_previous_login_3rd_party = req.cookies.is_previous_login_3rd_party === "true" ? true : false;
            }

            if (!is_previous_login_3rd_party) {
                const { redirect_to } = await acceptLogoutRequest(logout_challenge as string);
                res.redirect(redirect_to);
            } else {
                const { data } = await eacpPublicApi.post("/api/eacp/v1/auth1/getconfig");
                const signout = data.thirdauth.config.signout;
                const logoutUrl = data.thirdauth.config.logoutUrl;
                if (signout && logoutUrl) {
                    (res as Response).clearCookie("id_token");
                    (res as Response).clearCookie("client.oauth2_token");
                    (res as Response).clearCookie("client.oauth2_refresh_token");
                    (res as Response).clearCookie("expires_in");
                    (res as Response).clearCookie("token_type");
                    const url = `${logoutUrl}?service=${signout}`;
                    res.redirect(url);
                } else {
                    console.error(
                        `[${Date()}] [ERROR]
                        response": {
                            "status": 404,
                            "message": "第三方认证参数配置错误，请联系管理员检查。",
                            "data": {"message": "第三方认证参数配置错误，请联系管理员检查。","code": "404001111"
                        }`
                    );

                    throw {
                        response: {
                            status: 404,
                            message: "第三方认证参数配置错误，请联系管理员检查。",
                            data: {
                                message: "第三方认证参数配置错误，请联系管理员检查。",
                                code: 404001111,
                            },
                        },
                    };
                }
            }
        } catch (e) {
            const path = e && e.request && (e.request.path || (e.request._options && e.request._options.path));
            console.error(`[${Date()}] [ERROR]  ${path}  ERROR ${JSON.stringify(e && e.response && e.response.data)}`);
            if (e && e.response && e.response.status !== 503) {
                const { status, data } = e.response;
                res.statusCode = status;
                res.redirect(
                    `/oauth2/error?${
                        (
                            data &&
                            Object.keys(data).map(
                                (key) => `${encodeURIComponent(key)}=${encodeURIComponent(data[key])}`
                            )
                        ).join("&") || ""
                    }`
                );
            } else {
                const service = getServiceNameFromApi(path);
                console.error(`内部错误，连接${service}服务失败`);
                res.statusCode = 500;
                res.redirect(
                    `/oauth2/error?code=${getErrorCodeFromService(service)}&cause=${encodeURIComponent(
                        "内部错误"
                    )}&message=${encodeURIComponent(`连接${service}服务失败`)}`
                );
            }
        }
    } else {
        console.error(`参数不合法，缺少logout_challenge参数`);
        res.statusCode = 400;
        res.redirect(
            `/oauth2/error?code=${ErrorCode.INVALID_NO_LOGOUT_CHALLENGE}&cause=${encodeURIComponent(
                "参数不合法"
            )}&message=${encodeURIComponent("缺少logout_challenge参数")}`
        );
    }
};

export default signout;
